package com.gy.service.impl;

import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gy.controller.common.UploadController;
import com.gy.controller.common.UserHolder;
import com.gy.entity.research.Longitudinal;
import com.gy.mapper.LongitudinalMapper;
import com.gy.query.LongitudinalQuery;
import com.gy.result.Result;
import com.gy.service.LongitudinalService;
import com.gy.vo.PageVO;
import com.gy.vo.completed.CompletedLongitudinalVO;
import com.gy.vo.completed.ResultsCountVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.fasterxml.jackson.databind.type.LogicalType.Collection;

@Service
public class LongitudinalServiceImpl extends ServiceImpl<LongitudinalMapper, Longitudinal> implements LongitudinalService {
    @Autowired
    private LongitudinalMapper longitudinalMapper;
    @Autowired
    private UserServiceImpl userService;

    @Autowired
    private UploadController uploadController;

    @Override
    public Result<PageVO<Longitudinal>> getLongitudinal(LongitudinalQuery longitudinalQuery) {
        Long userId = UserHolder.getUser().getUserId();
        if (userId == null) {
            return Result.error("用户登录信息异常");
        }

        // 分页条件
        Page<Longitudinal> page = Page.of(longitudinalQuery.getPageNo(), longitudinalQuery.getPageSize());
        // 排序条件
        if (!longitudinalQuery.getSortBy().isEmpty() || longitudinalQuery.getIsAsc() != null) {
            page.addOrder(new OrderItem(longitudinalQuery.getSortBy(), longitudinalQuery.getIsAsc()));
        } else {
            // 为空，默认按照获得时间排序
            page.addOrder(new OrderItem("obtain_time", false));
        }

        // 构建查询条件
        LambdaQueryChainWrapper<Longitudinal> longitudinalLambdaQueryChainWrapper = lambdaQuery()
                .eq(userId != null, Longitudinal::getUserId, userId); // 根据用户ID查询

        // 只在开始日期和结束日期不为空且有效时添加 between 条件
        if (longitudinalQuery.getStartTime() != null && longitudinalQuery.getEndTime() != null) {
            try {
                // 可以根据需求调整日期格式
                Date startDate = new SimpleDateFormat("yyyy-MM-dd").parse(longitudinalQuery.getStartTime());
                Date endDate = new SimpleDateFormat("yyyy-MM-dd").parse(longitudinalQuery.getEndTime());
                longitudinalLambdaQueryChainWrapper.between(Longitudinal::getStartTime, startDate, endDate);
            } catch (ParseException e) {
                // 处理日期解析错误
                System.err.println("Invalid date format: " + e.getMessage());
            }
        }

        //添加个人排名查询参数
        if (longitudinalQuery.getRank() != null) {
            longitudinalLambdaQueryChainWrapper.eq(Longitudinal::getRank, longitudinalQuery.getRank());
        }
        // 分页查询
        Page<Longitudinal> longitudinalPage = longitudinalLambdaQueryChainWrapper.page(page);

        // 封装结果
        PageVO<Longitudinal> vo = new PageVO<>();
        vo.setTotal(longitudinalPage.getTotal());
        vo.setPages(longitudinalPage.getPages());
        List<Longitudinal> records = longitudinalPage.getRecords();

        if (records == null || records.isEmpty()) {
            vo.setList(Collections.emptyList());
        } else {
            vo.setList(records);
        }

        return Result.success(vo);
    }

    @Override
    @Transactional
    public Result removeLongitudinalById(Long id) {
        Longitudinal longitudinal = getById(id);
        if (longitudinal == null) {
            return Result.error("纵向研究信息未找到");
        }

        String filePath = longitudinal.getPdfPath();

        // 检查 filePath 是否为空
        if (filePath != null && !filePath.isEmpty()) {
            try {
                uploadController.deleteFile(filePath);
            } catch (Exception e) {
                return Result.error("删除文件失败");
            }
        } else {
            log.warn("filePath 为空，无需删除文件");
        }

        boolean removed = removeById(id);
        userService.decrementUserLongitudinalCount();
        if (!removed) {
            return Result.error("删除纵向研究信息失败");
        }

        return Result.success("纵向研究信息删除成功");
    }

    @Override
    public Result updateLongitudinal(Longitudinal longitudinal) {
        // 参数验证
        if (longitudinal == null) {
            return Result.error("纵向研究信息不能为空");
        }
        if (longitudinal.getId() == null) {
            return Result.error("纵向课题ID不能为空");
        }

        try {
            // 更新纵向课题数据
            int affectedRows = longitudinalMapper.updateLongitudinal(longitudinal);
            if (affectedRows > 0) {
                return Result.success(longitudinal);
            } else {
                return Result.error("未找到对应的纵向课题进行更新");
            }
        } catch (Exception e) {
            // 记录日志
            log.error("更新纵向课题信息时发生异常", e);
            return Result.error("更新纵向课题信息失败");
        }
    }

    @Override
    @Transactional
    public Result saveLongitudinal(Longitudinal longitudinal) {
        if (longitudinal == null) {
            log.warn("传入的纵向课题对象为空");
            return Result.error("纵向课题对象不能为空");
        }

        try {
            // Step 2: Set user ID, ensuring the user is authenticated
            Long userId = UserHolder.getUser().getUserId();
            if (userId == null) {
                return Result.error("用户登录信息异常");
            }
            longitudinal.setUserId(userId);

            // Step 3: Save the longitudinal research data
            boolean saved = longitudinalMapper.saveLongitudinal(longitudinal);  // Using MyBatis Plus's save() method
            if (!saved) {
                return Result.error("新增纵向课题失败");
            }
            userService.incrementUserLongitudinalCount();

            // Step 5: Return success response
            return Result.success("新增纵向课题成功");
        } catch (Exception e) {
            // Step 6: Handle any exceptions and log them
            log.error("保存纵向课题时发生异常", e);
            return Result.error("系统错误，请稍后再试");
        }
    }

    @Override
    public Result getLongitudinalByIds(Long[] ids) {
        // 验证传入的ID数组
        if (ids != null && ids.length > 0) {
            try {
                // 使用原生 MyBatis 查询纵向课题
                List<Longitudinal> longitudinalList = longitudinalMapper.selectLongitudinalBatchIds(Arrays.asList(ids));

                // 返回查询结果
                if (longitudinalList != null && !longitudinalList.isEmpty()) {
                    return Result.success(longitudinalList);
                } else {
                    return Result.error("未找到相关纵向课题信息");
                }
            } catch (Exception e) {
                log.error("根据多个id查询纵向课题时发生异常", e);
                return Result.error("查询纵向课题失败");
            }
        }
        return Result.error("未提供有效的纵向课题ID");
    }

    @Override
    public Longitudinal getLongitudinalById(Long id) {
        if (id == null) {
            return null;
        }
        return longitudinalMapper.selectLongitudinalById(id);
    }

    /**
     * 结题助手中查询已结题的纵向课题
     * @return
     */
    @Override
    public Result<List<CompletedLongitudinalVO>> getCompletedLongitudinal() {
        Long userId = UserHolder.getUser().getUserId();
        if (userId == null) {
            return Result.error("用户登录信息异常");
        }

        // 构建查询条件
        LambdaQueryChainWrapper<Longitudinal> queryWrapper = lambdaQuery()
                .eq(Longitudinal::getUserId, userId)
                .eq(Longitudinal::getProjectStatus, "结题");

        List<Longitudinal> completedLongitudinals = queryWrapper.list();

        // 调整线程池的配置
        ExecutorService executor = new ThreadPoolExecutor(
                4,  // 核心线程数
                20, // 最大线程数
                60L, TimeUnit.SECONDS, // 线程空闲超时时间
                new SynchronousQueue<>(), // 使用SynchronousQueue，这样任务不会进入队列
                new ThreadPoolExecutor.CallerRunsPolicy() // 使用CallerRunsPolicy拒绝策略
        );

        List<CompletableFuture<CompletedLongitudinalVO>> completedVOsFutures = completedLongitudinals.stream()
                .map(longitudinal -> CompletableFuture.supplyAsync(() -> {
                    // 各个成果的查询
                    List<CompletableFuture<List<ResultsCountVO>>> futureList = Arrays.asList(
                            CompletableFuture.supplyAsync(() -> selectResults("论文", userId, longitudinal.getId()), executor),
                            CompletableFuture.supplyAsync(() -> selectResults("专利", userId, longitudinal.getId()), executor),
                            CompletableFuture.supplyAsync(() -> selectResults("个人奖励", userId, longitudinal.getId()), executor),
                            CompletableFuture.supplyAsync(() -> selectResults("媒体报道", userId, longitudinal.getId()), executor),
                            CompletableFuture.supplyAsync(() -> selectResults("著作权", userId, longitudinal.getId()), executor),
                            CompletableFuture.supplyAsync(() -> selectResults("学生奖励", userId, longitudinal.getId()), executor),
                            CompletableFuture.supplyAsync(() -> selectResults("继续教育材料", userId, longitudinal.getId()), executor),
                            CompletableFuture.supplyAsync(() -> selectResults("著作", userId, longitudinal.getId()), executor)
                    );

                    // 等待所有任务完成
                    CompletableFuture<Void> allOf = CompletableFuture.allOf(futureList.toArray(new CompletableFuture[0]));

                    return allOf.thenApply(v -> {
                        List<ResultsCountVO> allResults = futureList.stream()
                                .map(CompletableFuture::join)  // 使用 join 替代 get
                                .flatMap(List::stream)
                                .collect(Collectors.toList());

                        int relatedResultsCount = allResults.size();

                        return CompletedLongitudinalVO.builder()
                                .projectName(longitudinal.getProjectName())
                                .projectLevel(longitudinal.getProjectLevel())
                                .projectNumber(longitudinal.getProjectNumber())
                                .startTime(String.valueOf(longitudinal.getStartTime()))
                                .projectStatus(longitudinal.getProjectStatus())
                                .resultsCountVO(allResults)
                                .relatedResultsCount(relatedResultsCount)
                                .build();
                    }).join();  // 阻塞调用，等待任务完成并返回结果
                }).exceptionally(ex -> {
                    // 处理异常
                    return null;
                }))
                .collect(Collectors.toList());

        // 等待所有任务完成
        List<CompletedLongitudinalVO> completedVOs = completedVOsFutures.stream()
                .map(CompletableFuture::join)  // 等待每个任务完成
                .collect(Collectors.toList());

        // 关闭线程池
        executor.shutdown();

        // 返回结果
        return Result.success(completedVOs);
    }

    private List<ResultsCountVO> selectResults(String type, Long userId, Long projectId) {
        List<ResultsCountVO> results = new ArrayList<>();

        switch (type) {
            case "论文":
                results = longitudinalMapper.selectPapersByUserIdAndProjectId(userId, projectId);
                results.forEach(result -> result.setType("相关论文"));
                break;
            case "专利":
                results = longitudinalMapper.selectPatentsByUserIdAndProjectId(userId, projectId);
                results.forEach(result -> result.setType("相关专利"));
                break;
            case "个人奖励":
                results = longitudinalMapper.selectPersonalAwardByUserIdAndProjectId(userId, projectId);
                results.forEach(result -> result.setType("相关个人获奖"));
                break;
            case "媒体报道":
                results = longitudinalMapper.selectReportByUserIdAndProjectId(userId, projectId);
                results.forEach(result -> result.setType("相关媒体报道"));
                break;
            case "著作权":
                results = longitudinalMapper.selectCopyRightByUserIdAndProjectId(userId, projectId);
                results.forEach(result -> result.setType("相关著作权"));
                break;
            case "学生奖励":
                results = longitudinalMapper.selectStudentAwardByUserIdAndProjectId(userId, projectId);
                results.forEach(result -> result.setType("相关学生获奖"));
                break;
            case "继续教育材料":
                results = longitudinalMapper.selectContinuingByUserIdAndProjectId(userId, projectId);
                results.forEach(result -> result.setType("相关继续教育材料"));
                break;
            case "著作":
                results = longitudinalMapper.selectPublicationByUserIdAndProjectId(userId, projectId);
                results.forEach(result -> result.setType("相关著作"));
                break;
            default:
                // In case no valid type is provided, we return an empty list
                return new ArrayList<>();
        }

        return results;
    }











}
